<!-- Copyright 2012 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// -->
<!DOCTYPE html>
<title>Unit Test of e2e.CipherMode.CFB</title>
<script src="../../../../../javascript/closure/base.js"></script>
<script src="test_js_deps-runfiles.js"></script>
<script>
  goog.require('e2e.cipher.Aes');
  goog.require('e2e.ciphermode.Cfb');
  goog.require('goog.array');
  goog.require('goog.testing.jsunit');
</script>
<script>
  function testConsistency() {
    var aes = new e2e.cipher.Aes(e2e.cipher.Algorithm.AES128,
                                         {key:goog.array.repeat(0x77, 16)});
    var aescfb = new e2e.ciphermode.Cfb(aes);
    var iv = goog.array.repeat(0x77, aes.blockSize);
    var plaintext = goog.array.repeat(0x22, 75);
    var ciphertext = e2e.async.Result.getValue(aescfb.encrypt(plaintext, iv));
    assertEquals("Size of ciphertext is same as plaintext.",
                 plaintext.length,
                 ciphertext.length);
    var deciphered = e2e.async.Result.getValue(aescfb.decrypt(ciphertext, iv));
    assertArrayEquals("Consistency on encryption/decryption.",
                      plaintext,
                      deciphered);
  }

  function testSmallPlaintext() {
    var aes = new e2e.cipher.Aes(e2e.cipher.Algorithm.AES128,
                                         {key:goog.array.repeat(0x77, 16)});
    var aescfb = new e2e.ciphermode.Cfb(aes);
    var iv = goog.array.repeat(0x77, aes.blockSize);
    var plaintext = goog.array.repeat(0x22, 1);
    var ciphertext = e2e.async.Result.getValue(aescfb.encrypt(plaintext, iv));
    assertEquals("Size of ciphertext is same as plaintext.",
                 plaintext.length,
                 ciphertext.length);
    var deciphered = e2e.async.Result.getValue(aescfb.decrypt(ciphertext, iv));
    assertArrayEquals("Consistency on encryption/decryption.",
                      plaintext,
                      deciphered);
  }

  function testTestVectors() {
    // NIST SP 800-38A test vectors
    var aes = new e2e.cipher.Aes(
        e2e.cipher.Algorithm.AES128,
        {
          key: [
            0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
            0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
          ]
        });
    var aesctr = new e2e.ciphermode.Cfb(aes);
    var iv = [
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
    ];
    var testvector = [
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
        0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
        0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
        0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
        0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
        0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
        0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
    ];

    var expectedCipherText = [
        0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
        0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
        0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
        0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
        0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
        0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
        0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
        0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6
    ];
    var cipherText = e2e.async.Result.getValue(aesctr.encrypt(testvector, iv))
    assertArrayEquals(expectedCipherText, cipherText);
  }
</script>
